﻿using System;
using System.Net;
using System.Linq;
using MEFedMVVM.ViewModelLocator;
using System.ComponentModel.Composition;
using Cinch;

using Microsoft.Maps.MapControl;
using System.Collections.ObjectModel;
using System.Collections;
using System.Xml;
using System.IO;
using WebProject.ServiceReferenceMap;
using WebProject.Controls;
using System.ComponentModel;
using System.Windows;

namespace WebProject.ViewModels
{

    [ExportViewModel("MapPageViewModel")]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class MapPageViewModel : ViewModelBase
    {
        //Constructor
        public MapPageViewModel()
        {
            MapPageText = "MapPageViewModel";
            CredentialsProvider = "AhYfF92PBowAMewWaHB6VxExehTnXmv9GsvmWXsuX1JqIqmbyG3pf4HmI0YcdA9m";
            Load();
            ButtonClickCommand = new DelegateCommand(PerformClickAction);

        }

        //PropertyChanged Event
        public new event PropertyChangedEventHandler PropertyChanged;
        //global MyLocation
        public LocationData MyLocation { get; set; }
        public string MapPageText { get; set; }
        //Button, Binding XAML
        public DelegateCommand ButtonClickCommand { get; set; }
        //MapID
        public string CredentialsProvider { get; set; }
        //Observable PinList
        public ObservableCollection<LocationData> _PinData = new ObservableCollection<LocationData>();
        public ObservableCollection<LocationData> PinData
        {
            get { return this._PinData; }
            set
            {
                if (this._PinData == value) return;
                this._PinData = value;
                this.OnPropertyChanged(new PropertyChangedEventArgs("PinData"));
            }
        }
        //txtLocationBox , Binding Xaml
        public string _MyLocationName = "Brehmestraße 59, 13187 Berlin";
        public string MyLocationName
        {
            get { return this._MyLocationName; }
            set
            {
                if (this._MyLocationName == value) return;
                this._MyLocationName = value;
                this.OnPropertyChanged(new PropertyChangedEventArgs("MyLocationName"));
            }
        }
        // This is the global internal variable where results are stored. These are accessed later to calculate the route.
        internal ServiceReferenceGeo.GeocodeResult[] geocodeResults;
        //OnPropertyChanged
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, e);
        }
        //Load LocationDataList, Pins
        public void Load()
        {
            var proxy = new MapServiceClient();
            proxy.LocationDataListCompleted += ProxyLocationDataListCompleted;
            proxy.LocationDataListAsync();

            //Load LocationDataList, Pins without Webservice
            #region Without Webservice
            // _PinData.Add(new LocationData
            //    {
            //        CustomerId = 10003,
            //        CustomerName = "Jack",
            //        Location = new Location(40.941352, -73.871310)
            //    });

            // _PinData.Add(new LocationData
            // {
            //     CustomerId = 10001,
            //     CustomerName = "Aaron",
            //     Location = new Location(43.778926, -73.958068)
            // });

            // _PinData.Add(new LocationData
            //{
            //    CustomerId = 10002,
            //    CustomerName = "Gabriel",
            //    Location = new Location(41.003764, -75.494192)
            //});
            #endregion

        }
        //Calling web service, if data are complete 
        private void ProxyLocationDataListCompleted(object sender, LocationDataListCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                foreach (var item in e.Result)
                    _PinData.Add(new LocationData
                    {
                        CustomerId = item.CustomerId,
                        CustomerName = item.CustomerName,
                        Location = new Location(item.Lat, item.Lng)
                    });
            }

            if (this.MyLocation != null)
                _PinData.Add(new LocationData
                {
                    CustomerId = this.MyLocation.CustomerId,
                    CustomerName = this.MyLocation.CustomerName,
                    Location = this.MyLocation.Location
                });
        }
        //Button Click Action
        public void PerformClickAction(object sender)
        {
            MessageBox.Show("Click");

            // Initialize the length of the results array. In this sample we have two waypoints.
            geocodeResults = new ServiceReferenceGeo.GeocodeResult[2];

            // Make the two Geocode requests using the values of the text boxes. Also pass the waypoint indexes 
            //   of these two values within the route.
            Geocode(this.MyLocationName, 0);


        }
        //Search a Location , Lat, Lag
        private void Geocode(string strAddress, int waypointIndex)
        {
            // Create the service variable and set the callback method using the GeocodeCompleted property.
            ServiceReferenceGeo.GeocodeServiceClient geocodeService = new ServiceReferenceGeo.GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
            geocodeService.GeocodeCompleted += new EventHandler<ServiceReferenceGeo.GeocodeCompletedEventArgs>(geocodeService_GeocodeCompleted);

            // Set the credentials and the geocode query, which could be an address or location.
            ServiceReferenceGeo.GeocodeRequest geocodeRequest = new ServiceReferenceGeo.GeocodeRequest();
            geocodeRequest.Credentials = new Credentials();
            geocodeRequest.Credentials.ApplicationId = (new ApplicationIdCredentialsProvider(this.CredentialsProvider)).ApplicationId;
            geocodeRequest.Query = strAddress;

            // Make the asynchronous Geocode request, using the ‘waypoint index’ as 
            //   the user state to track this request and allow it to be identified when the response is returned.
            geocodeService.GeocodeAsync(geocodeRequest, waypointIndex);
        }
        // This is the Geocode request callback method.
        private void geocodeService_GeocodeCompleted(object sender, ServiceReferenceGeo.GeocodeCompletedEventArgs e)
        {
            // Retrieve the user state of this response (the ‘waypoint index’) to identify which geocode request 
            //   it corresponds to.
            int waypointIndex = System.Convert.ToInt32(e.UserState);

            // Retrieve the GeocodeResult for this response and store it in the global variable geocodeResults, using
            //   the waypoint index to position it in the array.
            geocodeResults[waypointIndex] = e.Result.Results[0];

            // Look at each element in the global gecodeResults array to figure out if more geocode responses still 
            //   need to be returned.

            this.MyLocation = new LocationData();
            foreach (ServiceReferenceGeo.GeocodeResult gr in geocodeResults)
            {
                if (gr != null)
                {
                    this.MyLocation.CustomerId = 1000;
                    this.MyLocation.CustomerName = gr.DisplayName;
                    this.MyLocation.Location = new Location(gr.Locations[0].Latitude, gr.Locations[0].Longitude);
                }

            }

            LocationData myLocationTmp = this.PinData.Where(c => c.CustomerId == 1000).FirstOrDefault();
            if (myLocationTmp != null) this.PinData.Remove(myLocationTmp);

            if (this.MyLocation.Location == null) MessageBox.Show("Ort wurde nicht gefunden");
            else this.PinData.Add(MyLocation);

        }
    }


    /// <summary>
    /// This class contains an embedded Location object. It acts as DataContext
    /// for the individual items within MapItemsControl. Thus {Binding Location} translates to LocationData.Location
    /// </summary>
    public class LocationData
    {
        public Location Location { get; set; }
        public String CustomerName { get; set; }
        public Int32 CustomerId { get; set; }
        public LocationData() { this.Location = new Location(); }
    }



}
